<!--
 * @Autor: 王琛
 * @Description: 菜单滚动容器
 * @Copyright: 版权归个人所有
-->
<style lang="stylus" scoped>
#menuScrollContainer {
  width: 100%;
  height: 100%;
  position: relative;
  display: grid;
  grid-template-rows:100%;
  grid-template-columns: 20px calc(100% - 40px) 20px;
  place-items: center;

  .scrollArea {
    width: 100%;
    height: 100%;
    position: relative;
    overflow: hidden;

    & > div {
      display: grid;
      grid-template-rows:auto;
      place-items: center;
      transform: translateX(10px);
      transition: all .5s;
      grid-gap: 10px;

    }
  }
}

#menuScrollContainer.menuScrollContainer {
  padding: 0px 10px;
  box-sizing: border-box;
  grid-template-columns:100%;
  place-content: center;
}
</style>


<template>
  <div id="menuScrollContainer" :class="{ menuScrollContainer:true || !_data.moveConfig.isScroll }">
    <!--  左滚按钮  -->
    <van-icon v-show="false && _data.moveConfig.isScroll" name="arrow-left" color="#fff" size="20" @click="displacement({ mark:'left' })"/>
    <!-- 滚动区域 -->
    <div class="scrollArea" ref="scrollArea" v-move-directive="_data.moveConfig">
      <div id="scrollArea_child" ref="scrollArea_child" :style="{ gridTemplateColumns:`repeat(${ _props.col },auto)`,transform:`translateX(${ _data.moveConfig.currentDistance }px)` }">
        <slot></slot>
      </div>
    </div>
    <!--  有滚按钮  -->
    <van-icon v-show="false && _data.moveConfig.isScroll" name="arrow" color="#fff" size="20" @click="displacement({ mark:'right' })"/>
  </div>
</template>

<script setup lang="ts">
import {nextTick, onBeforeUnmount, onMounted, reactive, ref, watch} from "vue";
import {useRouter} from "vue-router";
import {useStore} from "vuex";
import {Icon} from "vant"
import {overlayEmits} from "element-plus";

const _store = useStore();
const _state = _store.state;
const _props = defineProps({
  // 确定有几个元素
  col: {
    type: Number,
    default: 11,
  },
})
const _data = reactive({
  moveConfig: {
    // 主容器宽度
    mainBox: '',
    // 子容器宽度
    chilcBox: '',
    // 滚动距离
    scrollDistance: 0,
    // 实际滚动距离
    currentDistance: 0,
    //
    isScroll: true,
  },
});
const vMoveDirective = {

  beforeMount: (el, config) => {
    let start = 0, end = 0;
    // 开始
    el.ontouchstart = (event) => {
      start = event.touches[0].pageX;
    }
    // 移动
    el.ontouchmove = (event) => {
      // 如果位移距离是负责则不需要滚动
      if (config.value.scrollDistance < 0) return;
      // 正数向右移,负数向左移
      const over = event.touches[0].pageX - start;
      // 更新容器移动位置
      config.value.currentDistance += over;
      // 兼容容器不能移除不必要部分
      if (config.value.currentDistance >= 0) config.value.currentDistance = 0;
      if (config.value.currentDistance <= -(config.value.scrollDistance)) config.value.currentDistance = -(config.value.scrollDistance);
      // 更新初始点位
      start = event.touches[0].pageX;
    }
  }
}
const scrollArea = ref(null)
const scrollArea_child = ref(null);


onMounted(() => {
  calculateData();
})
defineExpose({
  subNavigationScroll
})
watch(() => _state.screenWH, () => {
  calculateData()
})

/**
 * @description: 计算数据
 * @author: 王琛
 * @Date: 2022-07-20 15:26:15
 * @param {*}
 * @return {*}
 */
let calculateDataInterval: any = null;

function calculateData(): void {
  if (Array.from(scrollArea_child.value.children).length <= 0) return;
  // if (Array.from(scrollArea_child.value.children).length) {
  // 清除控制器
  // clearInterval(calculateDataInterval);
  // 主容器宽度
  const mainBox = scrollArea.value.clientWidth;
  // 子容器宽度
  let chilcBox = 0;
  Array.from(scrollArea_child.value.children).forEach((e, i) => {
    chilcBox += e.clientWidth;
    if (i) chilcBox += 10;
  });
  _data.moveConfig.mainBox = mainBox;
  _data.moveConfig.chilcBox = chilcBox;
  _data.moveConfig.scrollDistance = chilcBox - mainBox;
  _data.moveConfig.singleDisplacement = scrollArea_child.value.children[0].clientWidth;
  _data.moveConfig.isScroll = _data.moveConfig.scrollDistance > 0;
}

/**
 * @description: 点击了左右切换按钮
 * @author: 王琛
 * @Date: 2022-07-20 16:02:34
 * @param {*}
 * @return {*}
 */
function displacement({mark}) {
  // 如果位移距离是负责则不需要滚动
  if (_data.moveConfig.scrollDistance < 0) return;
  if (mark == "left") {
    _data.moveConfig.currentDistance += _data.moveConfig.singleDisplacement;
  } else {
    _data.moveConfig.currentDistance -= _data.moveConfig.singleDisplacement;
  }
  // 兼容容器不能移除不必要部分
  if (_data.moveConfig.currentDistance >= 0) _data.moveConfig.currentDistance = 0;
  if (_data.moveConfig.currentDistance <= -(_data.moveConfig.scrollDistance)) _data.moveConfig.currentDistance = -(_data.moveConfig.scrollDistance);
}

/**
 * @description: 计算子导航的滚动距离
 * @author: 王琛
 * @Date: 2022-07-08 17:13:14
 * @param {*}
 * @return {*}
 */
function subNavigationScroll({childEvent}) {
  // 当前的元素
  const _currentEl = childEvent.target;
  // 当前容器的宽度
  const _currentBoxWidth = _data.moveConfig.chilcBox
  // 主容器的宽度
  const _mainBoxWidth = _data.moveConfig.mainBox;
  // 极端可移动距离
  const _movingDistance = _currentBoxWidth - _mainBoxWidth;
  // 判断如果可移动距离小于0这不执行计算
  if (_movingDistance < 0) return
  // 当前移动距离
  let _currentMoveDistance = _currentEl.clientWidth / 2 + _currentEl.offsetLeft - _mainBoxWidth / 2;
  // 如果移动距离小于0,则设置为0,如果大于可移动距离则设置为移动距离
  if (_currentMoveDistance < 0) {
    _currentMoveDistance = 0;
  } else if (_currentMoveDistance > _movingDistance) {
    _currentMoveDistance = _movingDistance;
  }
  _data.moveConfig.currentDistance = -(_currentMoveDistance);
}

onBeforeUnmount(() => {
  // 清除本页面的定时器
  clearInterval(calculateDataInterval);
})
</script>

